﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using AsmFromGpp;
using LexicalAnalysisCs;
using TextDiffAlgoCs;

namespace UIWPF
{
    public static class CompareManager
    {
        public static void TextCompareBegin(RichTextBox rtb1, RichTextBox rtb2, RichTextBox hint, bool? colorized)
        {
//            CompareResult cr = new CompareResult();
//            double dg = cr.GetCompareRes(Utility.GetRichTextBoxContent(rtb1), Utility.GetRichTextBoxContent(rtb2));

//            List<TextDiff> diffList = cr.getDiffList;
            double deg1 = 0.0, deg2 = 0.0, degMixed = 0.0;
            List<TextDiff> diffList = TextComparer.Compare(RichTextBoxUtility.GetRichTextBoxContent(rtb1),
                                                           RichTextBoxUtility.GetRichTextBoxContent(rtb2),
                                                           ref deg1, ref deg2, ref degMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("\n--*TextDiff*--\n  *--Degree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 deg1*100.0, deg2*100.0, degMixed*100.0));

            if (colorized == true)
            {
                RichTextBoxUtility.Colorize(rtb1, 0, RichTextBoxUtility.GetRichTextBoxContent(rtb1).Length,
                                            Color.FromArgb(255, 0, 0, 255));
                RichTextBoxUtility.Colorize(rtb2, 0, RichTextBoxUtility.GetRichTextBoxContent(rtb2).Length,
                                            Color.FromArgb(255, 0, 0, 255));

                foreach (var td in diffList)
                {
                    switch (td.getDiffType)
                    {
                        case TextDiff.TYPE_DELETE:
                            RichTextBoxUtility.Colorize(rtb1, td.getDiffStartIndex, td.getDiffLength,
                                                        Color.FromArgb(255, 255, 0, 0));
                            break;
                        case TextDiff.TYPE_INSERT:
                            RichTextBoxUtility.Colorize(rtb2, td.getDiffStartIndex, td.getDiffLength,
                                                        Color.FromArgb(255, 255, 0, 0));
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        private static void ShowResult(List<TextDiff> diffList, List<LexicalAnalyzerCs.StrInt> lst1, List<LexicalAnalyzerCs.StrInt> lst2, RichTextBox rtb1, RichTextBox rtb2)
        {
            foreach (var td in diffList)
            {
                switch (td.getDiffType)
                {
                    case TextDiff.TYPE_DELETE:
                        for (int i = 0; i < td.getDiffLength; i++)
                        {
                            RichTextBoxUtility.Colorize(rtb1,
                                lst1[td.getDiffStartIndex + i].mEndIndex - lst1[td.getDiffStartIndex + i].mContent.Length,
                                lst1[td.getDiffStartIndex + i].mContent.Length + 1,
                                Color.FromArgb(255, 255, 0, 0));
                        }
                        break;
                    case TextDiff.TYPE_INSERT:
                        for (int i = 0; i < td.getDiffLength; i++)
                        {
                            RichTextBoxUtility.Colorize(rtb2,
                                lst2[td.getDiffStartIndex + i].mEndIndex - lst2[td.getDiffStartIndex + i].mContent.Length,
                                lst2[td.getDiffStartIndex + i].mContent.Length + 1,
                                Color.FromArgb(255, 255, 0, 0));
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        public static void ListCompareBegin(RichTextBox rtb1, RichTextBox rtb2, RichTextBox hint, bool? colorized)
        {
            // Create the tmp files so we can transfer the Cpp exe result into Cs projects.
            FileStream fs1 = new FileStream("inFile1.tmp", FileMode.Create);
            StreamWriter sw1 = new StreamWriter(fs1);
            sw1.Write(RichTextBoxUtility.GetRichTextBoxContent(rtb1));
            sw1.Close();
            fs1.Close();

            FileStream fs2 = new FileStream("inFile2.tmp", FileMode.Create);
            StreamWriter sw2 = new StreamWriter(fs2);
            sw2.Write(RichTextBoxUtility.GetRichTextBoxContent(rtb2));
            sw2.Close();
            fs2.Close();

            if (colorized == true)
            {
                RichTextBoxUtility.Colorize(rtb1, 0, RichTextBoxUtility.GetRichTextBoxContent(rtb1).Length,
                                            Color.FromArgb(255, 0, 0, 255));
                RichTextBoxUtility.Colorize(rtb2, 0, RichTextBoxUtility.GetRichTextBoxContent(rtb2).Length,
                                            Color.FromArgb(255, 0, 0, 255));
            }

            double includeDeg1 = 0.0, includeDeg2 = 0.0, includeDegMixed = 0.0;
            double namespaceDeg1 = 0.0, namespaceDeg2 = 0.0, namespaceDegMixed = 0.0;
            LexicalAnalyzerCs lac1 = new LexicalAnalyzerCs("inFile1.tmp", "outFile1.tmp");
            LexicalAnalyzerCs lac2 = new LexicalAnalyzerCs("inFile2.tmp", "outFile2.tmp");

            RichTextBoxUtility.RtbAppendStr(hint, String.Format("\n--*ListDiff*--\n"));

            // Result of comparing #include
            List<LexicalAnalyzerCs.StrInt> includeList1 = lac1.GetIncludeFileNames(true);
            List<LexicalAnalyzerCs.StrInt> includeList2 = lac2.GetIncludeFileNames(true);
            List<TextDiff> includeDiffList = ListComparer.Compare(includeList1, includeList2,
                                                                  ref includeDeg1, ref includeDeg2, ref includeDegMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Headers:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 includeDeg1 * 100.0, includeDeg2 * 100.0,
                                 includeDegMixed * 100.0));
            if (colorized == true)
            {
                ShowResult(includeDiffList, includeList1, includeList2, rtb1, rtb2);
            }

            // Result of comparing the using namespace;
            List<LexicalAnalyzerCs.StrInt> namespaceList1 = lac1.GetNamespaceName(true);
            List<LexicalAnalyzerCs.StrInt> namespaceList2 = lac2.GetNamespaceName(true);
            List<TextDiff> namespaceDiffList = ListComparer.Compare(namespaceList1, namespaceList2,
                                                                    ref namespaceDeg1, ref namespaceDeg2, ref namespaceDegMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Using Namespaces:\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 namespaceDeg1 * 100.0, namespaceDeg2 * 100.0,
                                 namespaceDegMixed * 100.0));
            if (colorized == true)
            {
                ShowResult(namespaceDiffList, namespaceList1, namespaceList2, rtb1, rtb2);
            }

            double wordsDeg1 = 0.0, wordsDeg2 = 0.0, wordsDegMixed = 0.0;
            double symbolsDeg1 = 0.0, symbolsDeg2 = 0.0, symbolsDegMixed = 0.0;
            List<LexicalAnalyzerCs.StrInt> wordsList1 = new List<LexicalAnalyzerCs.StrInt>();
            List<LexicalAnalyzerCs.StrInt> wordsList2 = new List<LexicalAnalyzerCs.StrInt>();
            List<LexicalAnalyzerCs.StrInt> symbolList1 = new List<LexicalAnalyzerCs.StrInt>();
            List<LexicalAnalyzerCs.StrInt> symbolList2 = new List<LexicalAnalyzerCs.StrInt>();
            lac1.GetWordsSymbolsList(ref wordsList1, ref symbolList1);
            lac2.GetWordsSymbolsList(ref wordsList2, ref symbolList2);

            wordsList1.Sort();
            wordsList2.Sort();
            symbolList1.Sort();
            symbolList2.Sort();

            List<TextDiff> wordsDiffList = ListComparer.Compare(wordsList1, wordsList2,
                                                                ref wordsDeg1, ref wordsDeg2, ref wordsDegMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Words:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 wordsDeg1 * 100.0, wordsDeg2 * 100.0,
                                 wordsDegMixed * 100.0));
            List<TextDiff> symbolDiffList = ListComparer.Compare(symbolList1, symbolList2,
                                                                 ref symbolsDeg1, ref symbolsDeg2, ref symbolsDegMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Symbols:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 symbolsDeg1 * 100.0, symbolsDeg2 * 100.0,
                                 symbolsDegMixed * 100.0));
            if (colorized == true)
            {
                ShowResult(wordsDiffList, wordsList1, wordsList2, rtb1, rtb2);
                ShowResult(symbolDiffList, symbolList1, symbolList2, rtb1, rtb2);
            }

            // Get the compare result showed.
            double deg1 = 0.0, deg2 = 0.0, degMixed = 0.0;
            List<LexicalAnalyzerCs.StrInt> resList1 = lac1.getResList;
            List<LexicalAnalyzerCs.StrInt> resList2 = lac2.getResList;
            List<TextDiff> diffList = ListComparer.Compare(resList1, resList2,
                                                           ref deg1, ref deg2, ref degMixed);
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Body:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                 deg1 * 100.0, deg2 * 100.0,
                                 degMixed*100.0));
            if (colorized == true)
            {
                ShowResult(diffList, resList1, resList2, rtb1, rtb2);
            }

            // Remember to delete the tmp files.
            File.Delete(@"inFile1.tmp");
            File.Delete(@"inFile2.tmp");
            File.Delete(@"outFile1.tmp");
            File.Delete(@"outFile2.tmp");
        }

        public static void AsmCompare(RichTextBox rtb1, RichTextBox rtb2, RichTextBox hint, bool? colorized)
        {
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("\n--*Asm Compare*--\n"));
            RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- This comparison auto add \"inline\" to the function, and only compare the main function\n"));

            FileStream fs1 = new FileStream("RichTextBox1.cpp", FileMode.Create);
            StreamWriter sw1 = new StreamWriter(fs1);
            sw1.Write(RichTextBoxUtility.GetRichTextBoxContent(rtb1) + '\n');
            sw1.Close();
            fs1.Close();

            FileStream fs2 = new FileStream("RichTextBox2.cpp", FileMode.Create);
            StreamWriter sw2 = new StreamWriter(fs2);
            sw2.Write(RichTextBoxUtility.GetRichTextBoxContent(rtb2) + '\n');
            sw2.Close();
            fs2.Close();

            CodeDecorating cd1 = new CodeDecorating("RichTextBox1.cpp", "rtb1Lex.out");
            CodeDecorating cd2 = new CodeDecorating("RichTextBox2.cpp", "rtb2Lex.out");
            cd1.InsertInlines();
            cd2.InsertInlines();
            cd1.OutputCodesToFile("RichTextBox1.cpp");
            cd2.OutputCodesToFile("RichTextBox2.cpp");

            int flag = 0;
            GenerateAsm ga1 = new GenerateAsm();
            GenerateAsm ga2 = new GenerateAsm();

            string tmp = "";
            try
            {
                tmp = ga1.GenAsmToFile("RichTextBox1.cpp");
                ga1.GenInstructionList();

                 RichTextBoxUtility.SetRichTextBoxContent(rtb1, ga1.MAsmCode);
//                 rtb1.Text = "";
//                 foreach (var gm in ga1.MAsmInstList)
//                 {
//                     rtb1.Text += gm.mContent;
//                     rtb1.Text += gm.mEndIndex.ToString() + '\n';
//                 }

//                  foreach (var si in ga1.MAsmOperandList)
//                  {
//                      Utility.Colorize(rtb1, si.mEndIndex - si.mContent.Length, si.mContent.Length + 1, Color.FromArgb(255, 0, 255, 255));
//                  }
                flag++;
            }
            catch
            {
                RichTextBoxUtility.SetRichTextBoxContent(rtb1, tmp);
                RichTextBoxUtility.RtbAppendStr(hint, String.Format("--*Asm Box1 Generated Crushed, might be the reason that the code cannot pass the compilation*--\n"));
            }

            try
            {
                tmp = ga2.GenAsmToFile("RichTextBox2.cpp");
                ga2.GenInstructionList();
                RichTextBoxUtility.SetRichTextBoxContent(rtb2, ga2.MAsmCode);
//                 rtb2.Text = "";
//                 foreach (var gm in ga2.MAsmInstList)
//                 {
//                     rtb2.Text += gm.mContent;
//                     rtb2.Text += gm.mEndIndex.ToString() + '\n';
//                 }
                flag++;
            }
            catch
            {
                RichTextBoxUtility.SetRichTextBoxContent(rtb2, tmp);
                RichTextBoxUtility.RtbAppendStr(hint, String.Format("--*Asm Box2 Generated Crushed, might be the reason that the code cannot pass the compilation*--\n"));
            }

            if (flag == 2)
            {
                RichTextBoxUtility.RtbAppendStr(hint, String.Format("--*Asm Generated Completed*--\n"));

                double opDeg1 = 0.0, opDeg2 = 0.0, opDegMixed = 0.0;
                List<TextDiff> opDiffList = ListComparer.Compare(ga1.MAsmOperandList, ga2.MAsmOperandList,
                                                                 ref opDeg1, ref opDeg2, ref opDegMixed);
                RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Operand:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                                          opDeg1 * 100.0, opDeg2 * 100.0,
                                                          opDegMixed * 100.0));
                if (colorized == true)
                {
                    ShowResult(opDiffList, ga1.MAsmOperandList, ga2.MAsmOperandList, rtb1, rtb2);
                }

                double instDeg1 = 0.0, instDeg2 = 0.0, instDegMixed = 0.0;
                List<TextDiff> diffList = ListComparer.Compare(ga1.MAsmInstList, ga2.MAsmInstList,
                                                               ref instDeg1, ref instDeg2, ref instDegMixed);
                RichTextBoxUtility.RtbAppendStr(hint, String.Format("  *-- Instruction:\t\tDegree1: {0:N3}% Degree2: {1:N3}% DegreeMixed: {2:N3}%\n",
                                                          instDeg1 * 100.0, instDeg2 * 100.0,
                                                          instDegMixed * 100.0));
                if (colorized == true)
                {
                    ShowResult(diffList, ga1.MAsmInstList, ga2.MAsmInstList, rtb1, rtb2);
                }
            }

            File.Delete("RichTextBox1.cpp");
            File.Delete("RichTextBox2.cpp");
            File.Delete("RichTextBox1.cpp.asm");
            File.Delete("RichTextBox2.cpp.asm");
        }
    }
}
